﻿#region Using

using System;
using System.Diagnostics;

#endregion

namespace GameLogic.Internal
{

    #region Using

    #endregion

    internal class GameTimeManager
    {
        private const bool SkipUpdateWhilePaused = true;

        private readonly Stopwatch stopwatch;

        private double lastUpdateTime;

        private float speedModifier;

        private double totalTimeSinceSpeedChanged;

        internal GameTimeManager()
        {
            this.stopwatch = new Stopwatch();
            this.speedModifier = 1.0f;
        }

        internal float SpeedModifier
        {
            get
            {
                return this.speedModifier;
            }

            set
            {
                this.totalTimeSinceSpeedChanged += this.stopwatch.ElapsedMilliseconds * this.speedModifier;
                this.speedModifier = value;
            }
        }

        internal event OnUpdateDelagate OnUpdate;

        internal void Pause()
        {
            this.stopwatch.Stop();
        }

        internal void Reset()
        {
            this.stopwatch.Reset();
            this.lastUpdateTime = 0;
            this.totalTimeSinceSpeedChanged = 0;
        }

        internal void Resume()
        {
            this.stopwatch.Start();
        }

        internal void Start()
        {
            this.stopwatch.Start();
        }

        internal void Update()
        {
            if (!this.stopwatch.IsRunning && SkipUpdateWhilePaused)
            {
                return;
            }

            var totalTime = this.stopwatch.ElapsedMilliseconds;
            var modifiedTotalTime = (totalTime * this.SpeedModifier) + this.totalTimeSinceSpeedChanged;
            var frameTime = modifiedTotalTime - this.lastUpdateTime;
            var gameTime = new GameTime(TimeSpan.FromMilliseconds(frameTime), TimeSpan.FromMilliseconds(modifiedTotalTime));
            this.lastUpdateTime = modifiedTotalTime;

            this.OnUpdate(gameTime);
        }

        internal delegate void OnUpdateDelagate(GameTime gameTime);
    }
}